<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <link rel="stylesheet" href="../cart.css" />
</head>

<body>
    <div id="app">
        <div class="container">
            <my-cart></my-cart>
        </div>
    </div>
    <script type="text/javascript" src="../vue.js"></script>
    <script type="text/javascript">
        // 3.在这里声明局部组件
        // 5.将对应的模板复制到各个局部组件
        var cartTitle = {
            // 8.子组件通过props属性 接收父组件传过来的值 这个值是自定义的属性名
            props: ['name'],
            template: `
      <!-- 6.在父组件data中return一个uname数据 -->
      <!-- 9.用插值表达式渲染到页面 -->
      <div class="title">{{name}}的商品</div>
      `,
        };
        var cartList = {
            // 17.将父组件的ulist 通过prop属性接收
            props: ['ulist'],
            // 18.将模板遍历 v-for :key 记得在src前加（填充属性记得加绑定）：绑定 并将数据动态填充进去
            template: `
          <div>
              <div class="item" v-for='item in ulist' :key='item.id'>
                  <img :src="item.img"/>
              <div class="name">{{item.name}}</div>
              <div class="change">
                  <!-- 32.给+ - 按钮注册点击事件 并且阻止a链接的跳转 并将id当做实参 -->
                  <a href="" @click.prevent='sub(item.id)'>－</a>
                  <!-- 27.实现商品数量输入框影响总价的功能 这里用@blur 失去焦点事件 然后在方法中携带id以及input事件-->
                  <input type="text" class="num" :value='item.num' @blur='changNum(item.id,$event)'/>
                  <a href="" @click.prevent='add(item.id)'>＋</a>
              </div>
              <!-- 19.删除功能 给删除按钮绑定点击事件 触发del方法-->
              <!-- 22.在del方法后面加上数据中id作为实参 也就是item.id-->
              <div class="del" @click='del(item.id)'>×</div>
              </div>
          </div>
      `,
            // 20.加一个methods
            methods: {
                // 注意点：子组件的数据是通过 props 得到的 这里不建议直接在子组件中删除 所以用子组件传值给父组件的方法 通过父组件来操作数据的删除
                // 21.删除基于数据中的id来操作 所以接收当前点击按钮对应的id
                del: function(id) {
                    // console.log(id);
                    // 22.将id传递给父组件 用到$emit()方法
                    this.$emit('del-shop', id);
                },
                // 28.修改对应的num值  需要根据id  以及输入框的值来操作
                changNum: function(id, event) {
                    // 29.传2个值 用对象形式 input输入框的值 用$event.target.value获取
                    this.$emit('change-num', {
                        type: 'change',
                        id: id,
                        num: event.target.value,
                    });
                },
                // 33.实现对加减按钮的功能
                add: function(id) {
                    this.$emit('change-num', {
                        id: id,
                        // 34.给3个方法添加type进行区分
                        type: 'add',
                    });
                },
                sub: function(id) {
                    this.$emit('change-num', {
                        id: id,
                        type: 'sub',
                    });
                },
            },
        };
        var cartTotal = {
            // 12.用props接收父组件传过来的数据ulist
            props: ['ulist'],
            template: `
              <div class="total">
                  <!-- 16.将计算出来的total属性直接用插值渲染 -->
                  <span>总价：{{total}}</span>
                  <button>结算</button>
              </div>
              `,
            // 13.对价格总价进行计算 需要用到computed属性
            computed: {
                total: function() {
                    // 14.定义一个变量t 便于计算总价格
                    var t = 0;
                    // 15.用forEach遍历ulist数组 记住cart-total模板中必须将list传值给:ulist 否则报错
                    this.ulist.forEach(function(item) {
                        t += item.num * item.price;
                    });
                    return t;
                },
            },
        };
        // 1.首先定义一个全局组件
        Vue.component('my-cart', {
            data: function() {
                return {
                    uname: '刘小青',
                    // 10.在父组件中填入数据
                    list: [{
                        id: 1,
                        name: 'TCL彩电',
                        price: 1000,
                        num: 1,
                        img: 'img/a.jpg',
                    }, {
                        id: 2,
                        name: '机顶盒',
                        price: 1000,
                        num: 1,
                        img: 'img/b.jpg',
                    }, {
                        id: 3,
                        name: '海尔冰箱',
                        price: 1000,
                        num: 1,
                        img: 'img/c.jpg',
                    }, {
                        id: 4,
                        name: '小米手机',
                        price: 1000,
                        num: 1,
                        img: 'img/d.jpg',
                    }, {
                        id: 5,
                        name: 'PPTV电视',
                        price: 1000,
                        num: 2,
                        img: 'img/e.jpg',
                    }, ],
                };
            },
            template: `
      <!-- 4.这里放对应的子组件  注意：加上根节点 -->
          <div class='cart'>
              <!-- 7.将uname 以属性的方式传值给cart-title 在模板中绑定一个自定义属性 并赋值uname -->
              <cart-title :name='uname'></cart-title>
              <!-- 11.将list 以属性的方式传值给 cart-list 在模板中绑定一个自定义属性 并赋值list-->
              <!-- 23.子组件通过$emit传值给父组件  在模板中用@ $emit的第一个参数='自定义的函数名'-->
              <!-- 30.子组件通过$emit传id和event值给父组件 在模板中用@ $emit的第一个参数='自定义的函数名'-->
              <cart-list :ulist='list' @del-shop="delShop($event)" @change-num='changeNums($event)'></cart-list>
              <cart-total :ulist='list'></cart-total>
          </div>
      `,
            // 2.拆分为三个子组件（局部组件）
            components: {
                'cart-title': cartTitle,
                'cart-list': cartList,
                'cart-total': cartTotal,
            },
            methods: {
                // 24.在这里定义一个delShop方法 将$event作为形参id使用
                delShop: function(id) {
                    // console.log(id);
                    // 25.拿到id后 需要在数组中找到相应下标=id的那一项数据 所以用到数组的findIndex方法 该方法返回的是一个索引
                    var index = this.list.findIndex((item) => {
                        return item.id == id;
                    });
                    // console.log(index);
                    // 26.拿到下标index后 通过数组splice方法 将对应下标数据移除
                    this.list.splice(index, 1);
                },
                changeNums: function(val) {
                    // console.log(val);
                    // 35.对3种修改商品数量的方法通过type进行判断
                    if (val.type == 'change') {
                        // 31.这里是数组的some方法 找到对应下标的数据
                        this.list.some((item) => {
                            if (item.id == val.id) {
                                item.num = val.num;
                                // 32.找到对应的数据后 停止遍历
                                return true;
                            }
                        });
                    } else if (val.type == 'sub') {
                        this.list.some((item) => {
                            if (item.id == val.id) {
                                // 36.当数值<1的时候让值为0 否则就继续-1
                                item.num < 1 ? (item.num = 0) : (item.num -= 1);
                                // 32.找到对应的数据后 停止遍历
                                return true;
                            }
                        });
                    } else if (val.type == 'add') {
                        this.list.some((item) => {
                            if (item.id == val.id) {
                                item.num += 1;
                                // 32.找到对应的数据后 停止遍历
                                return true;
                            }
                        });
                    }
                },
            },
        });
        var vm = new Vue({
            el: '#app',
            data: {},
        });
    </script>
</body>

</html>